/* $Id:area.cc $ */
/*
   Copyright (C) 2007 by Jurjen Stellingwerff <jurjen@stwerff.xs4all.nl>
   Part of the Moros Project http://moros.sourceforge.net/

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 3.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/

#define DEBUG_ROUTINE "area"

#include <sstream>
#include <fstream>
#include "../general/util.h"
#include "../general/log.h"
#include "../general/channel.h"
#include "area.h"
#include "../general/general.h"

area::area() {
    nr=0;
    terrain=-1;
    river_e=-1;
    river_ne=-1;
    river_nw=-1;
    road_e=-1;
    road_ne=-1;
    road_nw=-1;
}

// Field : nr

const int area::getNr() const { return nr; }
void area::setNr(const int v) { nr=v; }
int area::operator<(const class area &ck) const { return (this->nr < ck.nr)?1:0; }

// Field : terrain

const string areaTerrain[]={"ocean","coast","ford","lava","ice","cave","field","grass","forest","tropical","dirt","swamp","desert","deserthills","desertmountains","mountains"};
const int area::getTerrain() const { return terrain; }
const string area::showTerrain() const {
    if (terrain<0) return "";
    else return areaTerrain[terrain];
}
void area::setTerrain(const int  v) {
    if (v<0 || (unsigned int)v >= sizeof areaTerrain/sizeof areaTerrain[0]) terrain=-1;
    else terrain=v;
}
void area::setTerrain(const string v) {
    terrain=-1;
    loopArray(areaTerrain, tp, string) {
        if (v==*tp) {terrain=tp_i; break; }
    }
    if (terrain==-1) dbg_state("Enumerate area.terrain unknown '%s'", v.c_str());
}

// Field : river_e

const string areaRiver_e[]={"open","river","river_dike","dike","wall"};
const int area::getRiver_e() const { return river_e; }
const string area::showRiver_e() const {
    if (river_e<0) return "";
    else return areaRiver_e[river_e];
}
void area::setRiver_e(const int  v) {
    if (v<0 || (unsigned int)v >= sizeof areaRiver_e/sizeof areaRiver_e[0]) river_e=-1;
    else river_e=v;
}
void area::setRiver_e(const string v) {
    river_e=-1;
    loopArray(areaRiver_e, tp, string) {
        if (v==*tp) {river_e=tp_i; break; }
    }
    if (river_e==-1) dbg_state("Enumerate area.river_e unknown '%s'", v.c_str());
}

// Field : river_ne

const string areaRiver_ne[]={"open","river","river_dike","dike","wall"};
const int area::getRiver_ne() const { return river_ne; }
const string area::showRiver_ne() const {
    if (river_ne<0) return "";
    else return areaRiver_ne[river_ne];
}
void area::setRiver_ne(const int  v) {
    if (v<0 || (unsigned int)v >= sizeof areaRiver_ne/sizeof areaRiver_ne[0]) river_ne=-1;
    else river_ne=v;
}
void area::setRiver_ne(const string v) {
    river_ne=-1;
    loopArray(areaRiver_ne, tp, string) {
        if (v==*tp) {river_ne=tp_i; break; }
    }
    if (river_ne==-1) dbg_state("Enumerate area.river_ne unknown '%s'", v.c_str());
}

// Field : river_nw

const string areaRiver_nw[]={"open","river","river_dike","dike","wall"};
const int area::getRiver_nw() const { return river_nw; }
const string area::showRiver_nw() const {
    if (river_nw<0) return "";
    else return areaRiver_nw[river_nw];
}
void area::setRiver_nw(const int  v) {
    if (v<0 || (unsigned int)v >= sizeof areaRiver_nw/sizeof areaRiver_nw[0]) river_nw=-1;
    else river_nw=v;
}
void area::setRiver_nw(const string v) {
    river_nw=-1;
    loopArray(areaRiver_nw, tp, string) {
        if (v==*tp) {river_nw=tp_i; break; }
    }
    if (river_nw==-1) dbg_state("Enumerate area.river_nw unknown '%s'", v.c_str());
}

// Field : road_e

const string areaRoad_e[]={"nothing","broken","normal","good"};
const int area::getRoad_e() const { return road_e; }
const string area::showRoad_e() const {
    if (road_e<0) return "";
    else return areaRoad_e[road_e];
}
void area::setRoad_e(const int  v) {
    if (v<0 || (unsigned int)v >= sizeof areaRoad_e/sizeof areaRoad_e[0]) road_e=-1;
    else road_e=v;
}
void area::setRoad_e(const string v) {
    road_e=-1;
    loopArray(areaRoad_e, tp, string) {
        if (v==*tp) {road_e=tp_i; break; }
    }
    if (road_e==-1) dbg_state("Enumerate area.road_e unknown '%s'", v.c_str());
}

// Field : road_ne

const string areaRoad_ne[]={"nothing","broken","normal","good"};
const int area::getRoad_ne() const { return road_ne; }
const string area::showRoad_ne() const {
    if (road_ne<0) return "";
    else return areaRoad_ne[road_ne];
}
void area::setRoad_ne(const int  v) {
    if (v<0 || (unsigned int)v >= sizeof areaRoad_ne/sizeof areaRoad_ne[0]) road_ne=-1;
    else road_ne=v;
}
void area::setRoad_ne(const string v) {
    road_ne=-1;
    loopArray(areaRoad_ne, tp, string) {
        if (v==*tp) {road_ne=tp_i; break; }
    }
    if (road_ne==-1) dbg_state("Enumerate area.road_ne unknown '%s'", v.c_str());
}

// Field : road_nw

const string areaRoad_nw[]={"nothing","broken","normal","good"};
const int area::getRoad_nw() const { return road_nw; }
const string area::showRoad_nw() const {
    if (road_nw<0) return "";
    else return areaRoad_nw[road_nw];
}
void area::setRoad_nw(const int  v) {
    if (v<0 || (unsigned int)v >= sizeof areaRoad_nw/sizeof areaRoad_nw[0]) road_nw=-1;
    else road_nw=v;
}
void area::setRoad_nw(const string v) {
    road_nw=-1;
    loopArray(areaRoad_nw, tp, string) {
        if (v==*tp) {road_nw=tp_i; break; }
    }
    if (road_nw==-1) dbg_state("Enumerate area.road_nw unknown '%s'", v.c_str());
}

void area::save(class channel &ch) {
    ch.write("area", "");
    ch.write("n", getNr());
    ch.write("t", getTerrain());
    ch.write("r", getRiver_e());
    ch.write("ri", getRiver_ne());
    ch.write("ri5", getRiver_nw());
    ch.write("ro", getRoad_e());
    ch.write("ro7", getRoad_ne());
    ch.write("ro8", getRoad_nw());
}

void area::load(class channel &ch) {
    if (ch.key=="n" || ch.key=="nr") { setNr(atoi(ch.value.c_str())); ch.next(); }
    if (ch.key=="t" || ch.key=="terrain") { setTerrain(ch.value); ch.next(); }
    if (ch.key=="r" || ch.key=="river_e") { setRiver_e(ch.value); ch.next(); }
    if (ch.key=="ri" || ch.key=="river_ne") { setRiver_ne(ch.value); ch.next(); }
    if (ch.key=="ri5" || ch.key=="river_nw") { setRiver_nw(ch.value); ch.next(); }
    if (ch.key=="ro" || ch.key=="road_e") { setRoad_e(ch.value); ch.next(); }
    if (ch.key=="ro7" || ch.key=="road_ne") { setRoad_ne(ch.value); ch.next(); }
    if (ch.key=="ro8" || ch.key=="road_nw") { setRoad_nw(ch.value); ch.next(); }
}

void area::xml(ofstream &f, int l, int r) {
    f << ncpy(l, "  ") << "<area nr=\"" << getNr() <<
    "\" terrain=\"" << showTerrain() <<
    "\" river_e=\"" << showRiver_e() <<
    "\" river_ne=\"" << showRiver_ne() <<
    "\" river_nw=\"" << showRiver_nw() <<
    "\" road_e=\"" << showRoad_e() <<
    "\" road_ne=\"" << showRoad_ne() <<
    "\" road_nw=\"" << showRoad_nw() <<
    "\"/>" << endl;
}

// Repository

areaRepository area_repo;

areaRepository::areaRepository() { max_nr=0; }
class area& areaRepository::getArea(const int v) { return areas[v]; }
void areaRepository::setArea(class area& v) {
    if (v.getNr()==0) v.setNr(++max_nr);
    areas[v.getNr()]=v;
}
map<int,class area>& areaRepository::listArea() { return areas; }
void areaRepository::delArea(const int v) { areas.erase(v); }
const bool areaRepository::isArea(const int v) const { return areas.count(v)>0; }
void areaRepository::save(class channel &ch) {
    loopAreas(rec) {
        rec->save(ch);
    }
}

bool areaRepository::load(class channel &ch) {
    if (ch.key=="area") {
        ch.next();
        class area rec;
        rec.load(ch);
        setArea(rec);
        return true;
    }
    return false;
}
